package com.lzh.persevere.aop;

import com.lzh.persevere.annotation.ViewCount;
import com.lzh.persevere.mapper.ArticleInfoMapper;
import com.lzh.persevere.utils.SecurityUtils;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import javax.sql.DataSource;
import java.lang.reflect.Method;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;

/**
 * 浏览量统计切面
 * 拦截带有 @ViewCount 注解的方法，自动累加浏览量
 */
@Aspect
@Component
public class ViewCountAspect {

    @Resource
    private DataSource dataSource;

    @Resource
    private ArticleInfoMapper articleInfoMapper;

    /**
     * 切入点：拦截所有带有 @ViewCount 注解的方法
     */
    @Pointcut("@annotation(com.lzh.persevere.annotation.ViewCount)")
    public void viewCountPointcut() {
    }

    /**
     * 后置通知：方法执行成功后累加浏览量
     */
    @AfterReturning("viewCountPointcut()")
    public void afterReturning(JoinPoint joinPoint) throws Exception {
        // 1. 获取方法上的注解
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Method method = signature.getMethod();
        ViewCount viewCount = method.getAnnotation(ViewCount.class);

        // 2. 获取注解参数
        String idParam = viewCount.idParam();      // 主键参数名

        // 3. 从方法参数中获取主键ID
        Object[] args = joinPoint.getArgs();
        String[] paramNames = signature.getParameterNames();
        Long id = null;
        for (int i = 0; i < paramNames.length; i++) {
            if (paramNames[i].equals(idParam)) {
                id = Long.valueOf(args[i].toString()); // 转换为主键类型（假设为Long）
                break;
            }
        }
        if (id != null) {
            // 4. 执行浏览量累加
            articleInfoMapper.updateViewCount(id, 1, SecurityUtils.getUserId());
        }
    }

    /**
     * 获取实体类对应的表名（默认取类名首字母小写，可根据实际注解扩展）
     */
    private String getTableName(Class<?> entityClass) {
        // 这里简化处理，实际项目中可读取@Table注解的name属性
        String className = entityClass.getSimpleName();
        return Character.toLowerCase(className.charAt(0)) + className.substring(1);
    }

    /**
     * 执行更新SQL
     */
    private void executeUpdate(String sql, Long id) throws SQLException {
        try (Connection conn = dataSource.getConnection();
             PreparedStatement ps = conn.prepareStatement(sql)) {
            ps.setLong(1, id);
            ps.executeUpdate();
        }
    }
}